package cn.xspace.library.view.dialog.calendar;

import android.content.Context;
import android.graphics.Canvas;
import android.graphics.Color;
import android.graphics.Paint;
import android.text.TextUtils;
import android.util.AttributeSet;
import android.view.MotionEvent;
import android.view.View;
import android.view.ViewConfiguration;

import com.xspace.android.xafcommon.appliction.BaseApplication;
import com.xspace.android.xafcommon.been.BaseReturnBean;
import com.xspace.android.xafcommon.util.AppUtils;
import com.xspace.android.xafcommon.util.CalendarUtil;
import com.xspace.android.xafcommon.util.Constants;
import com.xspace.android.xafcommon.util.CustomDate;
import com.xspace.android.xafcommon.util.LogUtil;

import org.json.JSONException;
import org.json.JSONObject;

import java.util.ArrayList;
import java.util.Arrays;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

import cn.xspace.library.util.MyInfoUtil;
import cn.xspace.library.util.OkHttpManager;
import rx.android.schedulers.AndroidSchedulers;
import rx.functions.Action1;
import rx.schedulers.Schedulers;

/**
 * 自定义日历卡
 *
 * @author wuwenjie
 */
public class CalendarCard extends View {

    private static final int TOTAL_COL = 7; // 7列
    private static final int TOTAL_ROW = 6; // 6行

    /**
     * 缓存的数据,用于绘制背景
     */
    private static HashMap<String, HashMap<String, List<String>>> userMap = new HashMap<>();
    /**
     * 用于加载谁的日志信息,在创建对话框前需要先设置该参数
     */
    public static String userId = "";

    private Paint mCirclePaint; // 绘制圆形的画笔
    private Paint mTextPaint; // 绘制文本的画笔
    private Paint mBackGroundPaint; // 绘制背景的画笔
    private int mViewWidth; // 视图的宽度
    private int mViewHeight; // 视图的高度
    private int mCellSpace; // 单元格间距
    private Row rows[] = new Row[TOTAL_ROW]; // 行数组，每个元素代表一行
    private static CustomDate mShowDate; // 自定义的日期，包括year,month,day
    private static CustomDate mCurrentDate; // 当前的日期
    private OnCellClickListener mCellClickListener; // 单元格点击回调事件
    private int touchSlop; //
    private boolean callBackCellSpace;

    private Cell mClickCell;
    private float mDownX;
    private float mDownY;

    /**
     * 单元格点击的回调接口
     *
     * @author wuwenjie
     */
    public interface OnCellClickListener {
        void clickDate(CustomDate date); // 回调点击的日期

        void changeDate(CustomDate date); // 回调滑动ViewPager改变的日期
    }

    public CalendarCard(Context context, AttributeSet attrs, int defStyleAttr) {
        super(context, attrs, defStyleAttr);
        init(context);
    }

    public CalendarCard(Context context, AttributeSet attrs) {
        super(context, attrs);
        init(context);
    }

    public CalendarCard(Context context) {
        super(context);
        init(context);
    }

    public CalendarCard(Context context, OnCellClickListener listener) {
        super(context);
        this.mCellClickListener = listener;
        init(context);
    }

    private void init(Context context) {
        mTextPaint = new Paint(Paint.ANTI_ALIAS_FLAG);
        mCirclePaint = new Paint(Paint.ANTI_ALIAS_FLAG);
        mCirclePaint.setStyle(Paint.Style.FILL);
        mCirclePaint.setColor(Color.parseColor("#F24949")); // 红色圆形
        mBackGroundPaint = new Paint(Paint.ANTI_ALIAS_FLAG);
        mBackGroundPaint.setStyle(Paint.Style.FILL);
        mBackGroundPaint.setColor(Color.parseColor("#f0f0f0")); // 绘制背景

        touchSlop = ViewConfiguration.get(context).getScaledTouchSlop();

        initDate();
    }

    private void initDate() {
        mShowDate = new CustomDate();
        mCurrentDate = new CustomDate();
        requestData();
        fillDate();
    }

    private void fillDate() {
        int monthDay = CalendarUtil.getCurrentMonthDay(); // 今天
        int lastMonthDays = CalendarUtil.getMonthDays(mShowDate.year, mShowDate.month - 1); // 上个月的天数
        int currentMonthDays = CalendarUtil.getMonthDays(mShowDate.year, mShowDate.month); // 当前月的天数
        int firstDayWeek = CalendarUtil.getWeekDayFromDate(mShowDate.year, mShowDate.month);//获取当前月第一天是周几
        boolean isCurrentMonth = false;
        if (CalendarUtil.isCurrentMonth(mShowDate)) {
            isCurrentMonth = true;
        }
        int day = 0;
        for (int j = 0; j < TOTAL_ROW; j++) {
            rows[j] = new Row(j);
            for (int i = 0; i < TOTAL_COL; i++) {
                int position = i + j * TOTAL_COL; // 单元格位置
                // 当前月份
                if (position >= firstDayWeek && position < firstDayWeek + currentMonthDays) {
                    day++;
                    rows[j].cells[i] = new Cell(CustomDate.modifyDayForObject(mShowDate, day),
                            State.CURRENT_MONTH_DAY, i, j);
                    // 今天
                    if (isCurrentMonth && day == monthDay) {
                        CustomDate date = CustomDate.modifyDayForObject(mShowDate, day);
                        rows[j].cells[i] = new Cell(date, State.TODAY, i, j);
                    }

                    if (isCurrentMonth && day > monthDay) { // 如果比这个月的今天要大，表示还没到
                        rows[j].cells[i] = new Cell(CustomDate.modifyDayForObject(mShowDate, day),
                                State.UN_REACH_DAY, i, j);
                    }
                    // 过去一个月
                } else if (position < firstDayWeek) {
                    rows[j].cells[i] = new Cell(new CustomDate(mShowDate.year, mShowDate.month - 1,
                            lastMonthDays - (firstDayWeek - position - 1)), State.PAST_MONTH_DAY, i, j);
                    // 下个月
                } else if (position >= firstDayWeek + currentMonthDays) {
                    rows[j].cells[i] = new Cell((new CustomDate(mShowDate.year,
                            mShowDate.month + 1, position - firstDayWeek
                            - currentMonthDays + 1)),
                            State.NEXT_MONTH_DAY, i, j);
                }
                //背景绘制,判断是否需要绘制背景,且只绘制当前月份
                if (position >= firstDayWeek && position < firstDayWeek + currentMonthDays) {
                    int currentDay = position - firstDayWeek + 1; //当前的日期
                    String dayStr;
                    if (currentDay < 10) {
                        dayStr = "0" + currentDay;
                    } else {
                        dayStr = String.valueOf(currentDay);
                    }
                    if (mBackGroundList.size() > 0) {
                        if (mBackGroundList.contains(dayStr)) { //可以绘制背景
                            rows[j].cells[i].setHasBack(true);
                        }
                    }
                }
            }
        }
        mCellClickListener.changeDate(mShowDate);
    }

    @Override
    protected void onDraw(Canvas canvas) {
        super.onDraw(canvas);
        for (int i = 0; i < TOTAL_ROW; i++) {
            if (rows[i] != null) {
                rows[i].drawCells(canvas);
            }
        }
    }

    @Override
    protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
        super.onMeasure(widthMeasureSpec, heightMeasureSpec);
        mViewWidth = MeasureSpec.getSize(widthMeasureSpec);
        mCellSpace = mViewWidth / TOTAL_COL;
        mViewHeight = mCellSpace * TOTAL_ROW;
        int width = MeasureSpec.makeMeasureSpec(mViewWidth, MeasureSpec.EXACTLY);
        int height = MeasureSpec.makeMeasureSpec(mViewHeight, MeasureSpec.EXACTLY);
        setMeasuredDimension(width, height);
    }

    @Override
    protected void onSizeChanged(int w, int h, int oldw, int oldh) {
        super.onSizeChanged(w, h, oldw, oldh);
//        mViewWidth = w;
//        mViewHeight = h;
//        mCellSpace = Math.min(mViewHeight / TOTAL_ROW, mViewWidth / TOTAL_COL);
        if (!callBackCellSpace) {
            callBackCellSpace = true;
        }
        mTextPaint.setTextSize(mCellSpace / 3);
    }

    @Override
    protected void onLayout(boolean changed, int left, int top, int right, int bottom) {
        super.onLayout(changed, left, top, right, bottom);

    }

    @Override
    public boolean onTouchEvent(MotionEvent event) {
        switch (event.getAction()) {
            case MotionEvent.ACTION_DOWN:
                mDownX = event.getX();
                mDownY = event.getY();
                break;
            case MotionEvent.ACTION_UP:
                float disX = event.getX() - mDownX;
                float disY = event.getY() - mDownY;
                if (Math.abs(disX) < touchSlop && Math.abs(disY) < touchSlop) {
                    int col = (int) (mDownX / mCellSpace);
                    int row = (int) (mDownY / mCellSpace);
                    measureClickCell(col, row);
                }
                break;
            default:
                break;
        }

        return true;
    }

    /**
     * 计算点击的单元格
     *
     * @param col
     * @param row
     */
    private void measureClickCell(int col, int row) {
        if (col >= TOTAL_COL || row >= TOTAL_ROW)
            return;
        if (mClickCell != null) {
            rows[mClickCell.j].cells[mClickCell.i] = mClickCell;
        }
        if (rows[row] != null) {
            mClickCell = new Cell(rows[row].cells[col].date,
                    rows[row].cells[col].state, rows[row].cells[col].i,
                    rows[row].cells[col].j);

            CustomDate date = rows[row].cells[col].date;
            date.week = col;
            mCellClickListener.clickDate(date);

            // 刷新界面
            update();
        }
    }

    /**
     * 组元素
     *
     * @author wuwenjie
     */
    class Row {
        public int j;

        Row(int j) {
            this.j = j;
        }

        public Cell[] cells = new Cell[TOTAL_COL];

        // 绘制单元格
        public void drawCells(Canvas canvas) {
            for (Cell cell : cells) {
                if (cell != null) {
                    cell.drawSelf(canvas);
                }
            }
        }
    }

    /**
     * 单元格元素
     *
     * @author wuwenjie
     */
    class Cell {
        public CustomDate date;
        public State state;
        public boolean hasBack;
        public int i;
        public int j;

        public Cell(CustomDate date, State state, int i, int j) {
            super();
            this.date = date;
            this.state = state;
            this.i = i;
            this.j = j;
        }

        public void setHasBack(boolean hasBack) {
            this.hasBack = hasBack;
        }

        public void drawSelf(Canvas canvas) {
            switch (state) {
                case TODAY: // 今天
                    mTextPaint.setColor(Color.parseColor("#fffffe"));
                    canvas.drawCircle((float) (mCellSpace * (i + 0.5)),
                            (float) ((j + 0.5) * mCellSpace), mCellSpace / 3,
                            mCirclePaint);
                    break;
                case CURRENT_MONTH_DAY: // 当前月日期
                    mTextPaint.setColor(Color.BLACK);
                    if (hasBack) {
                        canvas.drawRect(mCellSpace * i, mCellSpace * j,
                                mCellSpace * (i + 1), mCellSpace * (j + 1),
                                mBackGroundPaint);
                    }
                    break;
                case PAST_MONTH_DAY: // 过去一个月
                case NEXT_MONTH_DAY: // 下一个月
                    mTextPaint.setColor(Color.parseColor("#fffffe"));
                    break;
                case UN_REACH_DAY: // 还未到的天
                    mTextPaint.setColor(Color.GRAY);
                    break;
                case EVENT:
                    mTextPaint.setColor(Color.GRAY);
                    break;
                default:
                    break;
            }
            // 绘制文字
            String content = date.day + "";
            canvas.drawText(content,
                    (float) ((i + 0.5) * mCellSpace - mTextPaint.measureText(content) / 2),
                    (float) ((j + 0.7) * mCellSpace - mTextPaint.measureText(content, 0, 1) / 2),
                    mTextPaint);
        }
    }

    /**
     * @author wuwenjie 单元格的状态 当前月日期，过去的月的日期，下个月的日期
     */
    enum State {
        TODAY, CURRENT_MONTH_DAY, PAST_MONTH_DAY, NEXT_MONTH_DAY, UN_REACH_DAY, EVENT
    }

    // 从左往右划，上一个月
    public void lastMonth() {
        if (mShowDate.month == 1) {
            mShowDate.month = 12;
            mShowDate.year -= 1;
        } else {
            mShowDate.month -= 1;
        }
        update();
    }

    // 从右往左划，下一个月
    public void nextMonth() {
        if (mShowDate.month == 12) {
            mShowDate.month = 1;
            mShowDate.year += 1;
        } else {
            mShowDate.month += 1;
        }
        update();
    }

    public void currentMonth() {
        mShowDate = new CustomDate();
        update();
    }

    public void update() {
        mBackGroundList.clear();
        if (mShowDate.year == mCurrentDate.year) { //今年的之前月份都可以查询
            if (mShowDate.month <= mCurrentDate.month) {
                requestData();
            }
        } else if (mShowDate.year < mCurrentDate.year) {//今年之前的日期也可以查询
            requestData();
        }
        //初次之外的月份不查询
        fillDate();
        invalidate();
    }

    private List<String> mBackGroundList = new ArrayList<>();

    private void requestData() {
        String month;
        if (mShowDate.month < 10) {
            month = "0" + mShowDate.month;
        } else {
            month = String.valueOf(mShowDate.month);
        }
        final String sTime = String.valueOf(mShowDate.year) + month;
        final int tempYear = mShowDate.year;
        final int tempMonth = mShowDate.month;
        if (TextUtils.isEmpty(userId)) { //userId在每次创建对话框时就更改,保证每次对话框的展示时userId唯一
            userId = MyInfoUtil.getMyUserid(BaseApplication.mInstance);
        }
        HashMap<String, List<String>> dayMap = userMap.get(userId);//从缓存中取数据
        if (dayMap != null) {
            List<String> stringList = dayMap.get(sTime);
            if (stringList != null) {
                LogUtil.d("wubaojie>>>缓存了背景数据userId: " + userId + " sTime:" + sTime + " 集合:" + stringList.toString());
                mBackGroundList.clear();
                mBackGroundList.addAll(stringList);
                return;
            }
        } else {
            userMap.put(userId, new HashMap<String, List<String>>());
        }
        if (!AppUtils.isConnected(BaseApplication.mInstance)) { //没网,直接返回
            return;
        }
        Map<String, Object> dataMap = new HashMap<>();
        dataMap.put("user_id", userId);
        dataMap.put("log_stime", sTime);

        OkHttpManager.getInstance().commonRequest(Constants.QUERY_WRITE_LOG_DATE, dataMap)
                .subscribeOn(Schedulers.io())
                .observeOn(AndroidSchedulers.mainThread())
                .subscribe(new Action1<BaseReturnBean>() {
                    @Override
                    public void call(BaseReturnBean baseReturnBean) {
                        try {
                            JSONObject object = new JSONObject(baseReturnBean.data);
                            String write_date = object.optString("write_date");
//                            if (mShowDate.year == tempYear && mShowDate.month == tempMonth) {
                            if (!TextUtils.isEmpty(write_date)) {
                                String[] split = write_date.split(",");
                                mBackGroundList.clear();
                                mBackGroundList.addAll(Arrays.asList(split));
                                userMap.get(userId).put(sTime, new ArrayList<>(mBackGroundList));
                                //重新刷新界面
                                fillDate();
                                invalidate();
                            } else {
                                userMap.get(userId).put(sTime, new ArrayList<String>());
                            }
//                            }
                        } catch (JSONException e) {
                            e.printStackTrace();
                        }
                    }
                });
    }
}
